HAL RCC Typical use cases for migration

System Clock Configuration

/**
  * Configure the system core clock only and activate it using the
  * HAL RCC unitary APIs (footprint optimization)
  *         The system Clock is configured as follow :
  *            System Clock source            = PLLCLK (MSIS)
  *            SYSCLK(Hz)                     = 160000000
  *            HCLK(Hz)                       = 160000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 1
  *            APB2 Prescaler                 = 1
  *            APB3 Prescaler                 = 1
  *            PLL1M                          = 1
  *            PLL1N                          = 80
  *            PLL1P                          = 2
  *            PLL1Q                          = 2
  *            PLL1R                          = 2
  *            Flash Latency(WS)              = 4
  * Initializes the CPU, AHB and APB bus clocks
  */

HAL1

HAL2

Initialize Voltage Scaling

HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
HAL_RCC_PWR_EnableClock();
HAL_PWR_SetMainRegulatorVoltageScalingRange(HAL_PWR_VOLTAGE_SCALING_RANGE_1);

Enable MSI Oscillator

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
HAL_RCC_MSIS_Enable(HAL_RCC_MSIS_FREQ_4MHZ);

Configure MSI Oscillator

RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_4;
HAL_RCC_MSI_SetTrimming(HAL_RCC_MSICALIBRATION_DEFAULT, HAL_RCC_MSI_RANGE_CALIB_4_TO_7);

Configure PLL

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 80;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_0;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
config_pll1.pll_source = HAL_RCC_PLLSOURCE_MSIS;
config_pll1.pll_m_boost = HAL_RCC_PLLMBOOST_DIV1;
config_pll1.pll_m = 1;
config_pll1.pll_n = 80;
config_pll1.pll_p = 2;
config_pll1.pll_q = 2;
config_pll1.pll_r = 2;
config_pll1.pll_fracn = 0;

Enable PLL

HAL_RCC_OscConfig(&RCC_OscInitStruct);
HAL_RCC_PLL1_SetConfig(&config_pll1);
HAL_RCC_PLL1_Enable();

Enable PLL Output

N/A

HAL_RCC_PLL1_EnableOutput(HAL_RCC_PLL1_SYSCLK);

Set Flash Latency

__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_4);
HAL_FLASH_SetLatency(flash1, FLASH_LATENCY_4);

Set System Clock Source

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLKSOURCE_PLLCLK);

Configure AHB and APB Prescalers

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
config_bus.ahb_clk_divider = HAL_RCC_HCLK_PRESCALER1;
config_bus.apb1_clk_divider = HAL_RCC_PCLK_PRESCALER1;
config_bus.apb2_clk_divider = HAL_RCC_PCLK_PRESCALER1;
config_bus.apb3_clk_divider = HAL_RCC_PCLK_PRESCALER1;
HAL_RCC_SetBusClockConfig(&config_bus);

Sequence diagram

@startuml
participant "Application" as App
participant "RCC" as RCC
participant "PWR" as PWR
participant "FLASH" as FLASH

App -> PWR: HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1)
App -> RCC: HAL_RCC_OscConfig(&RCC_OscInitStruct)
App -> RCC: HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4)
App -> FLASH: SystemCoreClockUpdate()
@enduml

Code Snippets

HAL1

HAL2

 int main(void)
 {
   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

   /** Configure the main internal regulator output voltage
   */
   if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
   {
     Error_Handler();
   }

   /** Initializes the CPU, AHB and APB buses clocks
   */
   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
   RCC_OscInitStruct.MSIState = RCC_MSI_ON;
   RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
   RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_4;
   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
   RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1;
   RCC_OscInitStruct.PLL.PLLM = 1;
   RCC_OscInitStruct.PLL.PLLN = 80;
   RCC_OscInitStruct.PLL.PLLP = 2;
   RCC_OscInitStruct.PLL.PLLQ = 2;
   RCC_OscInitStruct.PLL.PLLR = 2;
   RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_0;
   RCC_OscInitStruct.PLL.PLLFRACN = 0;
   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
   {
     Error_Handler();
   }

   /** Initializes the CPU, AHB and APB buses clocks
   */
   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                               |RCC_CLOCKTYPE_PCLK3;
   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
   RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;

   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
   {
     Error_Handler();
   }
}
int main(void)
{
   hal_rcc_bus_clk_config_t config_bus;
   hal_rcc_pll_config_t config_pll1;

   /** Configure the main internal regulator output voltage */

   HAL_RCC_PWR_EnableClock();

   if (HAL_PWR_SetMainRegulatorVoltageScalingRange(HAL_PWR_VOLTAGE_SCALING_RANGE_1) != HAL_OK)
   {
     Error_Handler();
   }

   HAL_RCC_MSIS_Enable(HAL_RCC_MSIS_FREQ_4MHZ);
   HAL_RCC_MSI_SetTrimming(HAL_RCC_MSICALIBRATION_DEFAULT, HAL_RCC_MSI_RANGE_CALIB_4_TO_7);

   config_pll1.pll_source  = HAL_RCC_PLLSOURCE_MSIS;
   config_pll1.pll_m_boost = HAL_RCC_PLLMBOOST_DIV1;
   config_pll1.pll_m       = 1;
   config_pll1.pll_n       = 80;
   config_pll1.pll_p       = 2;
   config_pll1.pll_q       = 2;
   config_pll1.pll_r       = 2;
   config_pll1.pll_fracn   = 0;

   if (HAL_RCC_PLL1_SetConfig(&config_pll1) != HAL_OK)
   {
     Error_Handler();
   }
   if (HAL_RCC_PLL1_Enable() != HAL_OK)
   {
     Error_Handler();
   }

   HAL_RCC_PLL1_EnableOutput(HAL_RCC_PLL1_SYSCLK);
   HAL_FLASH_SetLatency(flash1, FLASH_LATENCY_4);;
   HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLKSOURCE_PLLCLK);

   /** Initializes the CPU, AHB and APB bus clocks */
   config_bus.ahb_clk_divider  = HAL_RCC_HCLK_PRESCALER1;
   config_bus.apb1_clk_divider = HAL_RCC_PCLK_PRESCALER1;
   config_bus.apb2_clk_divider = HAL_RCC_PCLK_PRESCALER1;
   config_bus.apb3_clk_divider = HAL_RCC_PCLK_PRESCALER1;

   HAL_RCC_SetBusClockConfig(&config_bus);

Switch System Clock Source to HSI

/**
  * Configure the system core clock only and activate it using the
  * HAL RCC unitary APIs (footprint optimization)
  *         The system Clock is configured as follow :
  *            System Clock source            = PLLCLK (HSI)
  *            SYSCLK(Hz)                     = 80000000
  *            HCLK(Hz)                       = 80000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 2
  *            APB2 Prescaler                 = 1
  *            APB3 Prescaler                 = 1
  *            PLL1M                          = 1
  *            PLL1N                          = 80
  *            PLL1P                          = 2
  *            PLL1Q                          = 2
  *            PLL1R                          = 4
  *            Flash Latency(WS)              = 4
  * Initializes the CPU, AHB and APB bus clocks
  */

HAL1

HAL2

Select MSI as System Clock Source

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLKSOURCE_MSIS);

Set Flash Latency

__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_0);
HAL_FLASH_SetLatency(flash1, FLASH_LATENCY_0);

Enable HSI Oscillator and Configure PLL

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 2;
RCC_OscInitStruct.PLL.PLLN = 40;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 4;
HAL_RCC_HSI_Enable();
HAL_RCC_PLL1_Disable();
config_pll1.pll_source = HAL_RCC_PLLSOURCE_HSI;
config_pll1.pll_m_boost = HAL_RCC_PLLMBOOST_DIV1;
config_pll1.pll_m = 2;
config_pll1.pll_n = 40;
config_pll1.pll_p = 2;
config_pll1.pll_q = 2;
config_pll1.pll_r = 4;
config_pll1.pll_fracn = 0;
HAL_RCC_PLL1_SetConfig(&config_pll1);
HAL_RCC_PLL1_Enable();

Select PLL as System Clock Source

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2
| RCC_CLOCKTYPE_PCLK3);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
HAL_FLASH_SetLatency(flash1, FLASH_LATENCY_0);
HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLKSOURCE_PLLCLK);

Disable MSI Oscillator (Optional)

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_OFF;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_MSIS_Disable();

Sequence diagram

@startuml
participant "Application" as App
participant "RCC" as RCC
participant "PWR" as PWR
participant "FLASH" as FLASH

App -> RCC: HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0)
App -> RCC: HAL_RCC_OscConfig(&RCC_OscInitStruct)
App -> RCC: HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4)
App -> RCC: HAL_RCC_OscConfig(&RCC_OscInitStruct)
@enduml

Code Snippets

HAL1

HAL2

 int main(void)
 {
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  /* -1- Select MSI as system clock source to allow modification of the PLL configuration */
  RCC_ClkInitStruct.ClockType       = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource    = RCC_SYSCLKSOURCE_MSI;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

  /* -2- Enable HSI Oscillator, select it as PLL source and finally activate the PLL */
  RCC_OscInitStruct.OscillatorType       = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState             = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue  = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState         = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource        = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM             = 2;
  RCC_OscInitStruct.PLL.PLLN             = 40;
  RCC_OscInitStruct.PLL.PLLP             = 2;
  RCC_OscInitStruct.PLL.PLLQ             = 2;
  RCC_OscInitStruct.PLL.PLLR             = 4;

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

  /* -3- Select the PLL as system clock source and configure the bus clocks dividers */
  RCC_ClkInitStruct.ClockType       = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK
                                       | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2
                                       | RCC_CLOCKTYPE_PCLK3);
  RCC_ClkInitStruct.SYSCLKSource    = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider   = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider  = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider  = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB3CLKDivider  = RCC_HCLK_DIV1;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

  /* -4- Optional: Disable MSI Oscillator */
  RCC_OscInitStruct.OscillatorType  = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState        = RCC_MSI_OFF;
  RCC_OscInitStruct.PLL.PLLState    = RCC_PLL_NONE;  /* No update on PLL */
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
}
int main(void)
{

    hal_rcc_pll_config_t config_pll1;

    /* -1- Select MSI as system clock source to allow modification of the PLL configuration */
    if (HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLKSOURCE_MSIS) != HAL_OK)
    {
      /* Initialization Error */
      Error_Handler();
    }
    HAL_FLASH_SetLatency(flash1, FLASH_LATENCY_0);

    /* -2- Enable HSI Oscillator, select it as PLL source and finally activate the PLL */
    HAL_RCC_HSI_Enable();
    HAL_RCC_PLL1_Disable();

    config_pll1.pll_source  = HAL_RCC_PLLSOURCE_HSI;
    config_pll1.pll_m_boost = HAL_RCC_PLLMBOOST_DIV1;
    config_pll1.pll_m       = 2;
    config_pll1.pll_n       = 40;
    config_pll1.pll_p       = 2;
    config_pll1.pll_q       = 2;
    config_pll1.pll_r       = 4;
    config_pll1.pll_fracn   = 0;
    if (HAL_RCC_PLL1_SetConfig(&config_pll1) != HAL_OK)
    {
      Error_Handler();
    }

    if (HAL_RCC_PLL1_Enable() != HAL_OK)
    {
      Error_Handler();
    }

    HAL_RCC_PLL1_EnableOutput(HAL_RCC_PLL1_SYSCLK);
    config_bus.ahb_clk_divider  = HAL_RCC_HCLK_PRESCALER1;
    config_bus.apb1_clk_divider = HAL_RCC_PCLK_PRESCALER1;
    config_bus.apb2_clk_divider = HAL_RCC_PCLK_PRESCALER1;
    config_bus.apb3_clk_divider = HAL_RCC_PCLK_PRESCALER1;

   HAL_RCC_SetBusClockConfig(&config_bus);

    /* -3- Select the PLL as system clock source and configure the HCLK, PCLK1, PCLK2 and PCLK3 clocks dividers */
    HAL_FLASH_SetLatency(flash1, FLASH_LATENCY_4);
    if (HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLKSOURCE_PLLCLK) != HAL_OK)
    {
      /* Initialization Error */
      Error_Handler();
    }

    /* -4- Optional: Disable MSI Oscillator */
    if (HAL_RCC_MSIS_Disable() != HAL_OK)
    {
      /* Initialization Error */
      Error_Handler();
    }
}

Switch System Clock Source to MSI

/**
  * Configure the system core clock only and activate it using the
  * HAL RCC unitary APIs (footprint optimization)
  *         The system Clock is configured as follow :
  *            System Clock source            = PLLCLK (HSI)
  *            SYSCLK(Hz)                     = 48000000
  *            HCLK(Hz)                       = 48000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 1
  *            APB2 Prescaler                 = 1
  *            APB3 Prescaler                 = 1
  *            Flash Latency(WS)              = 1
  * Initializes the CPU, AHB and APB bus clocks
  */

HAL1

HAL2

Select HSI as System Clock Source

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLKSOURCE_HSI);

Set Flash Latency

__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_2);
HAL_FLASH_SetLatency(flash1, FLASH_LATENCY_2);

Enable MSI Oscillator and Configure parameters

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;
HAL_RCC_MSIS_Enable(HAL_RCC_MSIS_FREQ_48MHZ);
HAL_RCC_PLL1_Disable();

Select MSIS as System Clock Source

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK3);
RCC_ClkInitStruct.SYSCLKSource = HAL_RCC_SYSCLKSOURCE_MSIS;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
HAL_FLASH_SetLatency(flash1, FLASH_LATENCY_0);
HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLK_SRC_MSIS);

config_bus.ahb_clk_divider  = HAL_RCC_HCLK_PRESCALER1;
config_bus.apb1_clk_divider = HAL_RCC_PCLK_PRESCALER1;
config_bus.apb2_clk_divider = HAL_RCC_PCLK_PRESCALER1;
config_bus.apb3_clk_divider = HAL_RCC_PCLK_PRESCALER1;

     HAL_RCC_SetBusClockConfig(&config_bus);

Disable HSI Oscillator (Optional)

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_HSI_Disable();

Sequence diagram

@startuml
participant "Application" as App
participant "RCC" as RCC
participant "PWR" as PWR
participant "FLASH" as FLASH

App -> RCC: HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1)
App -> RCC: HAL_RCC_OscConfig(&RCC_OscInitStruct)
App -> RCC: HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4)
App -> RCC: HAL_RCC_OscConfig(&RCC_OscInitStruct)
@enduml

Code Snippets

HAL1

HAL2

int main(void)
{
   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
   RCC_OscInitTypeDef RCC_OscInitStruct = {0};

   /* -1- Select HSI as system clock source */
   RCC_ClkInitStruct.ClockType       = RCC_CLOCKTYPE_SYSCLK;
   RCC_ClkInitStruct.SYSCLKSource    = RCC_SYSCLKSOURCE_HSI;
   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
   {
     Error_Handler();
   }

   /* -2- Enable MSI Oscillator */
   RCC_OscInitStruct.OscillatorType      = RCC_OSCILLATORTYPE_MSI;
   RCC_OscInitStruct.MSIState            = RCC_MSI_ON;
   RCC_OscInitStruct.MSIClockRange       = RCC_MSIRANGE_48;
   RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
   RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_OFF;

   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
   {
     Error_Handler();
   }

   /* -3- Select the MSIS as system clock source */
   RCC_ClkInitStruct.ClockType       = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK
   | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK3);
   RCC_ClkInitStruct.SYSCLKSource    = RCC_SYSCLKSOURCE_PLLCLK;
   RCC_ClkInitStruct.AHBCLKDivider   = RCC_SYSCLK_DIV1;
   RCC_ClkInitStruct.APB1CLKDivider  = RCC_HCLK_DIV1;
   RCC_ClkInitStruct.APB2CLKDivider  = RCC_HCLK_DIV1;
   RCC_ClkInitStruct.APB3CLKDivider  = RCC_HCLK_DIV1;
   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
   {
     Error_Handler();
   }

   /* -4- Optional: Disable HSI Oscillator (if the HSI is no more needed by the application)*/
   RCC_OscInitStruct.OscillatorType  = RCC_OSCILLATORTYPE_HSI;
   RCC_OscInitStruct.HSIState        = RCC_HSI_OFF;
   RCC_OscInitStruct.PLL.PLLState    = RCC_PLL_NONE;  /* No update on PLL */
   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
   {
     Error_Handler();
   }
}
int main(void)
{

   /* -1- Select HSI as system clock source */
   if (HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLKSOURCE_HSI) != HAL_OK)
   {
     /* Initialization Error */
     Error_Handler();
   }
   HAL_FLASH_SetLatency(flash1, FLASH_LATENCY_0);

   /* -2- Enable MSI Oscillator */
   HAL_RCC_MSIS_Enable(HAL_RCC_MSIS_FREQ_48MHZ);
   HAL_RCC_PLL1_Disable();

    config_bus.ahb_clk_divider  = HAL_RCC_HCLK_PRESCALER1;
    config_bus.apb1_clk_divider = HAL_RCC_PCLK_PRESCALER1;
    config_bus.apb2_clk_divider = HAL_RCC_PCLK_PRESCALER1;
    config_bus.apb3_clk_divider = HAL_RCC_PCLK_PRESCALER1;

   HAL_RCC_SetBusClockConfig(&config_bus);

   /* -3- Select the MSIS as system clock source */
   HAL_FLASH_SET_LATENCY(flash1, FLASH_LATENCY_2);
   if (HAL_RCC_SetSysClkSource(HAL_RCC_SYSCLKSOURCE_MSIS) != HAL_OK)
   {
     /* Initialization Error */
     Error_Handler();
   }

   /* -4- Optional: Disable HSI Oscillator (if the HSI is no more needed by the application)*/
   if (HAL_RCC_HSI_Disable() != HAL_OK)
   {
     /* Initialization Error */
     Error_Handler();
   }
}

Note

Note: In HAL1, the configuration of the number of wait states for the flash memory was included in the RCC configuration functions. However, in HAL2, this configuration has been removed from the RCC functions and must now be done using a specific function in the flash driver.

Set peripheral clock source

Example 1: USART1 Clock Configuration

HAL1

HAL2

Set peripheral clock source

RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_HSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
    while (1);
}
HAL_RCC_USART1_SetKernelClkSource(HAL_RCC_USART1CLKSOURCE_HSI);

Example 2: ADC/DAC Clock Configuration

HAL1

HAL2

Set peripheral clock source

RCC_PeriphCLKInitTypeDef PeriphClkInit;

PeriphClkInit.PeriphClockSelection = AdcDacClockSelection;
PeriphClkInit.adc1ClockSelection = RCC_ADCDACCLKSOURCE_PLL2;

PeriphClkInit.PLL2.PLL2Source = RCC_PLLSOURCE_MSI;
PeriphClkInit.PLL2.PLL2M = 1;
PeriphClkInit.PLL2.PLL2N = 48;
PeriphClkInit.PLL2.PLL2P = 17;
PeriphClkInit.PLL2.PLL2Q = 2;
PeriphClkInit.PLL2.PLL2R = 2;
PeriphClkInit.PLL2.PLL2RGE = RCC_PLLVCIRANGE_0;
PeriphClkInit.PLL2.PLL2FRACN = 0;
PeriphClkInit.PLL2.PLL2ClockOut = RCC_PLL2_DIVR;

HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
hal_rcc_pll_config_t pll2_config;
pll2_config.pll_source = HAL_RCC_PLLSOURCE_MSIS;
pll2_config.pll_m = 1;
pll2_config.pll_n = 48;
pll2_config.pll_p = 17;
pll2_config.pll_q = 2;
pll2_config.pll_r = 2;
pll2_config.pll_fracn = 0;

HAL_RCC_PLL2_SetConfig(&pll2_config);
HAL_RCC_PLL2_Enable();
HAL_RCC_PLL2_EnableOutput(HAL_RCC_PLL2_OUTPUT_R);

HAL_RCC_ADCDAC_SetKernelClkSource(HAL_RCC_ADCDAC_CLK_SRC_PLL2R);

Get peripheral clock source

HAL1

HAL2

Get peripheral clock source

RCC_PeriphCLKInitTypeDef PeriphClkInit;
HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkInit);
uint32_t usart1_clk_source = PeriphClkInit.Usart1ClockSelection;
uint32_t usart1_clk_source = HAL_RCC_USART1_GetKernelClkSource();

Get peripheral clock frequency

HAL1

HAL2

Get peripheral clock frequency

uint32_t usart1_clk_freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_USART1);
/* Get peripheral clock frequency with unitary function */
uint32_t usart1_clk_freq = HAL_RCC_USART1_GetKernelClkFreq();

/* Get peripheral clock frequency with Global function */
uint32_t usart1_clk_freq = HAL_RCC_USART_GetKernelClkFreq(USART1);

HAL CRS typical use cases for migration

This section provides information about the HAL CRS typical use cases for migration.

In HAL1, the CRS functionality was implemented as a set of functions integrated within the HAL RCC driver.

In HAL2, the CRS feature has been refactored into a standalone HAL CRS driver, providing a more modular and consistent API similar to other HAL drivers. The main functions include:

  • Initialization and configuration via:

    • HAL_CRS_Init() to initialize the CRS handle and link it to the CRS instance.

    • HAL_CRS_SetConfig() to configure the CRS parameters.

  • Synchronization control via:

    • HAL_CRS_StartSync() to start synchronization.

    • HAL_CRS_PollForSync() to poll for synchronization completion.

Users can choose between polling mode or interrupt mode for synchronization management.

Interrupt Mode Differences Between HAL1 and HAL2

  • In HAL1:

    • After calling HAL_RCCEx_CRSConfig(), the user must manually:

      • Enable the CRS IRQ in the NVIC.

      • Enable CRS interrupts using macros such as __HAL_RCC_CRS_ENABLE_IT().

      • Handle synchronization events in weak callback functions invoked by HAL_RCCEx_CRS_IRQHandler().

  • In HAL2:

    • Synchronization is started with HAL_CRS_StartSync_IT(), which internally enables the required interrupts.

    • Callbacks can be handled by:

      • Overriding weak callback functions, or

      • Registering custom callbacks dynamically using dedicated APIs:

        • HAL_CRS_RegisterSyncOkCallback()

        • HAL_CRS_RegisterSyncWarnCallback()

        • HAL_CRS_RegisterExpectedSyncCallback()

        • HAL_CRS_RegisterErrorCallback()

    • The IRQ handler HAL_CRS_IRQHandler() dispatches these callbacks accordingly.

Enable synchronization in polling mode

HAL1

HAL2

@startuml

"User Application" -> "Driver RCC" : Initialize CRS within RCC config
"User Application" -> "Driver RCC" : HAL_RCCEx_CRSConfig()
"User Application" -> "Driver RCC" : HAL_RCCEx_CRSWaitSynchronization()

@enduml

@startuml

"User Application" -> "Driver CRS" : HAL_CRS_Init()
"User Application" -> "Driver CRS" : HAL_CRS_SetConfig()
"User Application" -> "Driver CRS" : HAL_CRS_StartSync()
"User Application" -> "Driver CRS" : HAL_CRS_PollForSync()

@enduml

HAL1

HAL2

uint32_t status = RCC_CRS_NONE;





/* Initialize the Init structure */
RCC_CRSInitTypeDef RCC_CRSInitStruct = {0};

/* Configure the CRS parameters */

RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;
RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_LSE;
RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING;
RCC_CRSInitStruct.ReloadValue =
                 __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000,32768);
RCC_CRSInitStruct.ErrorLimitValue = 34;
RCC_CRSInitStruct.HSI48CalibrationValue = 32;
/* The Auto Trimming is internally enabled in HAL_RCCEx_CRSConfig() */



/* Configure and start the driver with Frequency Error Counter
   and Automatic Trimming enabled in Polling mode */
HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct);

/* Check status of CRS synchronization */
status = HAL_RCCEx_CRSWaitSynchronization(1000);
hal_status_t status;

hal_crs_handle_t hcrs;

/* Initialize the CRS driver */
HAL_CRS_Init(&hcrs, HAL_CRS1);

hal_crs_config_t crs_config = {0};

/* Configure the CRS driver with Frequency Error Counter
   enabled and Automatic Trimming enabled */
crs_config.divider = HAL_CRS_SYNC_DIV1;
crs_config.source = HAL_CRS_SYNC_SOURCE_LSE;
crs_config.polarity = HAL_CRS_SYNC_POLARITY_RISING;
crs_config.reload = HAL_CRS_CALCULATE_RELOAD(48000000,32768);

crs_config.frequency_error_limit = 34;
crs_config.trimming = 32;
crs_config.auto_trimming = HAL_CRS_AUTO_TRIMMING_ENABLE;

HAL_CRS_SetConfig(&hcrs, &crs_config);

/* Start the driver with Frequency Error Counter enabled
   in Polling mode */
HAL_CRS_StartSync(&hcrs);

/* Retrieve the status of synchronization */
status = HAL_CRS_PollForSync(&hcrs,1000);

Software synchronization

In this use case, automatic synchronization is not used. Instead, the user regularly generates software synchronization events by calling the appropriate function.

  • In HAL1, the function to generate a software synchronization event is HAL_RCCEx_CRSSoftwareSynchronizationGenerate().

  • In HAL2, the corresponding function is HAL_CRS_GenerateSoftwareSync().

The application typically calls this function regularly within the SysTick interrupt handler to maintain synchronization without relying on automatic mode. This approach provides full control over synchronization timing and avoids using automatic synchronization for the start operation.

Users can manually synchronize the CRS by calling the software synchronization function either regularly during runtime (for example, within the SysTick or other interrupt handlers) or once at application startup. While this example uses the SysTick interrupt for convenience, the function can be invoked from any context suitable to the application, such as other interrupts, threads, or initialization routines.

HAL1

HAL2

@startuml

skinparam sequenceMessageAlign center

rnote over "System"
Activate SysTick
endrnote

"User Application"->"Driver RCC" : Enable the CRS clock within RCC configuration
"Driver RCC" -[#Green]-> "User Application" : return HAL_OK

"SYSTICK_IRQHandler" <[#Orange]- : SYSTICK interrupt

"SYSTICK_IRQHandler" -[#Orange]> "System" : HAL_SYSTICK_IRQHandler()

"User Application"->"Driver RCC" : HAL_RCCEx_CRSSoftwareSynchronizationGenerate()
"Driver RCC" --> "User Application"

@enduml

@startuml

skinparam sequenceMessageAlign center

rnote over "System"
Activate SysTick
endrnote

"User Application"->"Driver CRS" : HAL_CRS_Init()
"Driver CRS" -[#Green]-> "User Application" : return HAL_OK

"SYSTICK_IRQHandler" <[#Orange]- : SYSTICK interrupt

"SYSTICK_IRQHandler" -[#Orange]> "System" : HAL_CORTEX_SYSTICK_IRQHandler()

"User Application"->"Driver CRS" : HAL_CRS_GenerateSoftwareSync()
"Driver CRS" --> "User Application"

@enduml

HAL1

HAL2

/* */

/* Enable the CRS clock*/
__HAL_RCC_CRS_CLK_ENABLE();

/* Generate a software synchronization event */
HAL_RCCEx_CRSSoftwareSynchronizationGenerate();
hal_crs_handle_t hcrs;

/* Initialize the CRS driver */
HAL_CRS_Init(&hcrs, HAL_CRS1);

/* Generate a software synchronization event */
HAL_CRS_GenerateSoftwareSync(&hcrs);